<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
 <head>
  <meta http-equiv="content-type" content="text/html; charset=UTF-8">
  <title>不向后兼容的变更</title>
<link media="all" rel="stylesheet" type="text/css" href="styles/03e73060321a0a848018724a6c83de7f-theme-base.css" />
<link media="all" rel="stylesheet" type="text/css" href="styles/03e73060321a0a848018724a6c83de7f-theme-medium.css" />

 </head>
 <body class="docs"><div class="navbar navbar-fixed-top">
  <div class="navbar-inner clearfix">
    <ul class="nav" style="width: 100%">
      <li style="float: left;"><a href="migration74.constants.html">« 新的全局常量</a></li>
      <li style="float: right;"><a href="migration74.deprecated.html">PHP 7.4.x 废弃的功能 »</a></li>
    </ul>
  </div>
</div>
<div id="breadcrumbs" class="clearfix">
  <ul class="breadcrumbs-container">
    <li><a href="index.html">PHP Manual</a></li>
    <li><a href="migration74.html">从 PHP 7.3.x 移植到 PHP 7.4.x</a></li>
    <li>不向后兼容的变更</li>
  </ul>
</div>
<div id="layout">
  <div id="layout-content"><div id="migration74.incompatible" class="sect1">
 <h2 class="title">不向后兼容的变更</h2>

 <div class="sect2" id="migration74.incompatible.core">
  <h3 class="title">PHP 核心中不向后兼容的变更</h3>

  <div class="sect3" id="migration74.incompatible.core.non-array-access">
   <h4 class="title">以数组形式访问非数组</h4>

   <p class="para">
    尝试以数组方式访问 <span class="type">null</span>，<span class="type">bool</span>，
    <span class="type">int</span>，<span class="type">float</span> 或 <span class="type">resource</span>
    （例如 <code class="literal">$null[&quot;key&quot;]</code>）将会抛出 notice 通知。
   </p>
  </div>

  <div class="sect3" id="migration74.incompatible.core.get-declared-classes">
   <h4 class="title"><span class="function"><a href="function.get-declared-classes.html" class="function">get_declared_classes()</a></span> 函数</h4>

   <p class="para">
    <span class="function"><a href="function.get-declared-classes.html" class="function">get_declared_classes()</a></span>
    函数将不再返回匿名的类，假如它们没有被实例化的话。
   </p>
  </div>
  
  <div class="sect3" id="migration74.incompatible.core.fn">
   <h4 class="title"><code class="literal">fn</code> 关键词</h4>

   <p class="para">
    <code class="literal">fn</code> 成为了保留关键词。需要特别注意，它不能再做为函数名或类名使用，但是仍然可以做为方法名和常量名存在。
   </p>
  </div>

  <div class="sect3" id="migration74.incompatible.core.php-tag">
   <h4 class="title">文件尾部的 <code class="literal">&lt;?php</code> 标签</h4>

   <p class="para">
    文件尾部的 <code class="literal">&lt;?php</code>
    标签（不包含空行）将会被解释成一个 PHP 头标签。Previously it was interpreted
    either as a short opening tag followed by literal <code class="literal">php</code> and
    resulted in a syntax error (with <code class="literal">short_open_tag=1</code>)
    or was interpreted as a literal <code class="literal">&lt;?php</code> string
    (with <code class="literal">short_open_tag=0</code>).
   </p>
  </div>

  
  <div class="sect3" id="migration74.incompatible.core.stream-wrappers">
   <h4 class="title">Stream wrappers</h4>

   <p class="para">
    When using include/require on a stream,
    <span class="methodname"><a href="streamwrapper.stream-set-option.html" class="methodname">streamWrapper::stream_set_option()</a></span>
    will be invoked with the <strong><code>STREAM_OPTION_READ_BUFFER</code></strong> option.
    Custom stream wrapper implementations may need to implement the
    <span class="methodname"><a href="streamwrapper.stream-set-option.html" class="methodname">streamWrapper::stream_set_option()</a></span> method to
    avoid a warning (always returning <strong><code>false</code></strong> is a sufficient implementation).
   </p>
  </div>

  <div class="sect3" id="migration74.incompatible.core.serialization">
   <h4 class="title">Serialization 序列化</h4>

   <p class="para">
    序列化类型 <code class="literal">o</code> 被移除。因为它不是由 PHP
    生成的，这可能会影响到之前项目中手动生成的序列化字符串。
   </p>
  </div>

  
  <div class="sect3" id="migration74.incompatible.core.password-algorithm-constants">
   <h4 class="title">密码算法常量</h4>

   <p class="para">
    密码哈希算法标识符现在是可空字符串，而不再是整数。
   </p>

   <ul class="itemizedlist">
    <li class="listitem">
     <span class="simpara">
      <strong><code>PASSWORD_DEFAULT</code></strong> 之前是 int 1; 现在是“2y”（在 PHP 7.4.0、7.4.1、7.4.2 中是 <strong><code>null</code></strong>）
     </span>
    </li>
    <li class="listitem">
     <span class="simpara">
      <strong><code>PASSWORD_BCRYPT</code></strong> 之前是 int 1; 现在是 string &#039;2y&#039;
     </span>
    </li>
    <li class="listitem">
     <span class="simpara">
      <strong><code>PASSWORD_ARGON2I</code></strong> 之前是 int 2; 现在是 string &#039;argon2i&#039;
     </span>
    </li>
    <li class="listitem">
     <span class="simpara">
      <strong><code>PASSWORD_ARGON2ID</code></strong> 之前是 int 3; 现在是 string &#039;argon2id&#039;
     </span>
    </li>
   </ul>

   
   <p class="para">
    应用中如果正常使用了常量 PASSWORD_DEFAULT，PASSWORD_BCRYPT，PASSWORD_ARGON2I
    和 PASSWORD_ARGON2ID 将不会受到影响。
   </p>
  </div>

  
  <div class="sect3" id="migration74.incompatible.core.htmlentities">
   <h4 class="title"><span class="function"><a href="function.htmlentities.html" class="function">htmlentities()</a></span> 函数</h4>

   <p class="para">
    <span class="function"><a href="function.htmlentities.html" class="function">htmlentities()</a></span> will now raise a notice
    (instead of a strict standards warning) if it is used with
    an encoding for which only basic entity substitution is supported,
    in which case it is equivalent to <span class="function"><a href="function.htmlspecialchars.html" class="function">htmlspecialchars()</a></span>.
   </p>
  </div>

  <div class="sect3" id="migration74.incompatible.core.fread-fwrite">
   <h4 class="title"><span class="function"><a href="function.fread.html" class="function">fread()</a></span> and <span class="function"><a href="function.fwrite.html" class="function">fwrite()</a></span> 函数</h4>

   <p class="para">
    <span class="function"><a href="function.fread.html" class="function">fread()</a></span> 和 <span class="function"><a href="function.fwrite.html" class="function">fwrite()</a></span>
    在操作失败的时候会返回 <strong><code>false</code></strong>。之前的版本中会返回空字符串或 0。EAGAIN/EWOULDBLOCK 不视为故障。
   </p>
   <p class="para">
    这些函数现在也会在失败时发出 NOTICE 通知，例如当试图写入一个只读文件资源时。
   </p>
  </div>

 </div>

 <div class="sect2" id="migration74.incompatible.bcmath">
  <h3 class="title">BCMath 任意精度数学</h3>

  <p class="para">
   如果传递了例如 <code class="literal">&quot;32foo&quot;</code> 这种格式不正确的数字，BCMath 函数现在将发出警告。和以前一样，参数将解释为 0。
  </p>
 </div>

 <div class="sect2" id="migration74.incompatible.curl">
  <h3 class="title">CURL</h3>

  <p class="para">
   现在尝试序列化 <span class="classname"><a href="class.curlfile.html" class="classname">CURLFile</a></span> 类将会生成异常。之前仅会在反序列化时引发。
  </p>
  <p class="para">
   弃用 <strong><code>CURLPIPE_HTTP1</code></strong>，并在 cURL 7.62.0 起不再支持。
  </p>
  <p class="para">
   弃用 <span class="function"><a href="function.curl-version.html" class="function">curl_version()</a></span> 的 <code class="literal">$version</code> 参数。如果传递了任何不等于默认
   <strong><code>CURLVERSION_NOW</code></strong> 的值，则会引发警告并忽略参数。
  </p>
 </div>

 <div class="sect2" id="migration74.incompatible.datetime">
  <h3 class="title">日期和时间</h3>

  <p class="para">
   Calling <span class="function"><a href="function.var-dump.html" class="function">var_dump()</a></span> or similar on a
   <span class="classname"><a href="class.datetime.html" class="classname">DateTime</a></span> or <span class="classname"><a href="class.datetimeimmutable.html" class="classname">DateTimeImmutable</a></span>
   instance will no longer leave behind accessible properties on the object.
  </p>
  <p class="para">
   <span class="classname"><a href="class.dateinterval.html" class="classname">DateInterval</a></span> 对象的比较（使用
   <code class="literal">==</code>、<code class="literal">&lt;</code> 等）现在将生成警告并始终返回
   <strong><code>false</code></strong>。之前所有的 <span class="classname"><a href="class.dateinterval.html" class="classname">DateInterval</a></span> 对象都认为相等，除非它们有属性。
  </p>
 </div>

 <div class="sect2" id="migration74.incompatible.intl">
  <h3 class="title">Intl</h3>

  <p class="para">
   The default parameter value of <span class="function"><a href="function.idn-to-ascii.html" class="function">idn_to_ascii()</a></span> and
   <span class="function"><a href="function.idn-to-utf8.html" class="function">idn_to_utf8()</a></span> is now <strong><code>INTL_IDNA_VARIANT_UTS46</code></strong>
   instead of the deprecated <strong><code>INTL_IDNA_VARIANT_2003</code></strong>.
  </p>
 </div>

 <div class="sect2" id="migration74.incompatible.mysqli">
  <h3 class="title">MySQLi</h3>

  <p class="para">
   The embedded server functionality has been removed. It was broken since
   at least PHP 7.0.
  </p>
  <p class="para">
   The undocumented <code class="literal">mysqli::$stat</code> property has been removed
   in favor of <span class="methodname"><a href="mysqli.stat.html" class="methodname">mysqli::stat()</a></span>.
  </p>
 </div>

 <div class="sect2" id="migration74.incompatible.openssl">
  <h3 class="title">OpenSSL</h3>

  <p class="para">
   The <span class="function"><a href="function.openssl-random-pseudo-bytes.html" class="function">openssl_random_pseudo_bytes()</a></span> function will now
   throw an exception in error situations, similar to <span class="function"><a href="function.random-bytes.html" class="function">random_bytes()</a></span>.
   In particular, an <span class="classname"><a href="class.error.html" class="classname">Error</a></span> is thrown if the number of
   requested bytes is less than or equal to zero, and an <span class="classname"><a href="class.exception.html" class="classname">Exception</a></span>
   is thrown if sufficient randomness cannot be gathered.
   The <code class="literal">$crypto_strong output</code> argument is guaranteed to always
   be <strong><code>true</code></strong> if the function does not throw, so explicitly checking it is not necessary.
  </p>
 </div>

 <div class="sect2" id="migration74.incompatible.pcre">
  <h3 class="title">Regular Expressions (Perl-Compatible)</h3>

  <p class="para">
   When <strong><code>PREG_UNMATCHED_AS_NULL</code></strong> mode is used, trailing
   unmatched capturing groups will now also be set to <strong><code>null</code></strong> (or
   <code class="literal">[null, -1]</code> if offset capture is enabled).
   This means that the size of the <code class="literal">$matches</code> will always be the same.
  </p>
 </div>

 <div class="sect2" id="migration74.incompatible.pdo">
  <h3 class="title">PHP Data Objects</h3>

  <p class="para">
   Attempting to serialize a <span class="classname"><a href="class.pdo.html" class="classname">PDO</a></span> or
   <span class="classname"><a href="class.pdostatement.html" class="classname">PDOStatement</a></span> instance will now generate
   an <span class="classname"><a href="class.exception.html" class="classname">Exception</a></span> rather than a <span class="classname"><a href="class.pdoexception.html" class="classname">PDOException</a></span>,
   consistent with other internal classes which do not support serialization.
  </p>
 </div>

 <div class="sect2" id="migration74.incompatible.reflection">
  <h3 class="title">反射</h3>

  <p class="para">
   现在如果尝试对 Reflection 对象序列化将会生成异常。从未支持反射对象序列化并会引起反射对象错误。现在已明确禁止。
  </p>

  <p class="para">
   <span class="classname"><a href="class.reflectionclassconstant.html" class="classname">ReflectionClassConstant</a></span>、<span class="classname"><a href="class.reflectionmethod.html" class="classname">ReflectionMethod</a></span> 和
   <span class="classname"><a href="class.reflectionproperty.html" class="classname">ReflectionProperty</a></span> 类常量的值发生了变化。
  </p>
 </div>

 <div class="sect2" id="migration74.incompatible.spl">
  <h3 class="title">PHP 标准库（SPL）</h3>

  <p class="para">
   现在对 <span class="classname"><a href="class.arrayobject.html" class="classname">ArrayObject</a></span> 实例调用 <span class="function"><a href="function.get-object-vars.html" class="function">get_object_vars()</a></span>
   将始终返回 <span class="classname"><a href="class.arrayobject.html" class="classname">ArrayObject</a></span> 本身（或子类）的属性。
   Previously it returned the values of the wrapped
   array/object unless the <strong><code>ArrayObject::STD_PROP_LIST</code></strong>
   flag was specified.
  </p>
  <p class="para">
   其它受到影响的操作有：
  </p>
  <ul class="itemizedlist">
   <li class="listitem">
    <span class="simpara">
     <span class="methodname"><strong>ReflectionObject::getProperties()</strong></span>
    </span>
   </li>
   <li class="listitem">
    <span class="simpara">
     <span class="function"><a href="function.reset.html" class="function">reset()</a></span>、<span class="function"><a href="function.current.html" class="function">current()</a></span> 等等。
     改用 <span class="interfacename"><a href="class.iterator.html" class="interfacename">Iterator</a></span> 方法。
    </span>
   </li>
   <li class="listitem">
    <span class="simpara">
     可能将对象属性作为列表处理的其它情况。比如 <span class="function"><a href="function.array-walk.html" class="function">array_walk()</a></span>。
    </span>
   </li>
  </ul>
  <p class="para">
   <code class="literal">(array)</code> casts are not affected. They will continue to
   return either the wrapped array, or the <span class="classname"><a href="class.arrayobject.html" class="classname">ArrayObject</a></span>
   properties, depending on whether the <strong><code>ArrayObject::STD_PROP_LIST</code></strong>
   flag is used.
  </p>
  <p class="para">
   <span class="methodname"><a href="splpriorityqueue.setextractflags.html" class="methodname">SplPriorityQueue::setExtractFlags()</a></span> will throw
   an exception if zero is passed. Previously this would generate a recoverable
   fatal error on the next extraction operation.
  </p>
  <p class="para">
   <span class="classname"><a href="class.arrayobject.html" class="classname">ArrayObject</a></span>, <span class="classname"><a href="class.arrayiterator.html" class="classname">ArrayIterator</a></span>,
   <span class="classname"><a href="class.spldoublylinkedlist.html" class="classname">SplDoublyLinkedList</a></span> and <span class="classname"><a href="class.splobjectstorage.html" class="classname">SplObjectStorage</a></span>
   now support the <code class="literal">__serialize()</code> and <code class="literal">__unserialize()</code>
   mechanism in addition to the <span class="interfacename"><a href="class.serializable.html" class="interfacename">Serializable</a></span> interface.
   This means that serialization payloads created on older PHP versions can still be
   unserialized, but new payloads created by PHP 7.4 will not be understood by older versions.
  </p>
 </div>

 <div class="sect2" id="migration74.incompatible.tokenizer">
  <h3 class="title">Tokenizer</h3>

  <p class="para">
   <span class="function"><a href="function.token-get-all.html" class="function">token_get_all()</a></span> will now emit a
   <strong><code>T_BAD_CHARACTER</code></strong> token for unexpected
   characters instead of leaving behind holes in the token stream.
  </p>
 </div>

 <div class="sect2" id="migration74.incompatible.cookie-decode">
  <h3 class="title">接收到的 Cookies</h3>

  <p class="para">
   从 PHP 7.4.11 开始，为了安全考虑，接受到的 Cookie 中的 <em class="emphasis">names</em> 参数不再被
   URL 编码。
  </p>
 </div>

</div></div></div></body></html>